package infostroy.bookagolf.components.widgets;

import com.academysmart.bookagolf.i18n.Messages;
import com.sun.awt.AWTUtilities;
import infostroy.bookagolf.common.Constants.Colors;
import infostroy.bookagolf.common.Constants.Dimensions;
import infostroy.bookagolf.common.Constants.Icons;
import infostroy.bookagolf.common.helpers.ComponentsHelper;
import infostroy.bookagolf.common.helpers.ImageHelper;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

/**
 * Created by valer_000 on 2/24/14.
 */
public class GolfCalendar {

    private static final String CHOOSE_DATE = Messages.MainWindow_ChooseDate;

    private JLabel selectedMonth = new JLabel();
    private JPanel contentPanel = new JPanel(new BorderLayout());
    private JPanel headerPanel = new JPanel(new BorderLayout());
    private SimpleDateFormat dateFormat = new SimpleDateFormat("MMMM yyyy", Locale.getDefault());
    private Calendar calendar = Calendar.getInstance();
    private JPanel itemsPanel = new JPanel(new GridLayout(6, 7, 1, 1));

    private JComponent source;
    private CalendarCallback calendarCallback;
    private JDialog dialog;

    private boolean isPrepared;

    public GolfCalendar(JComponent source, CalendarCallback calendarCallback) {
        this.source = source;
        this.calendarCallback = calendarCallback;
    }

    private void prepareDialog() {
        dialog = new JDialog();
        dialog.setSize(Dimensions.CALENDAR_WIDGET_DIM.width
                , Dimensions.CALENDAR_WIDGET_DIM.height);
        dialog.setUndecorated(true);
        dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
        contentPanel.setBorder(new LineBorder(Color.BLACK, 1));
        dialog.add(this.contentPanel, BorderLayout.CENTER);
        dialog.setModal(true);
        AWTUtilities.setWindowOpaque(dialog, false);
    }

    private void initHeader() {
        JButton closeBtn = ComponentsHelper.createButtonWithImg(ImageHelper
                .getInstance().loadImage(Icons.RED_MARK));
        closeBtn.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                dialog.setVisible(false);
            }
        });
        JLabel title = new JLabel(CHOOSE_DATE);

        JPanel panel = new JPanel();
        panel.setBorder(new EmptyBorder(5, 5, 5, 0));
        panel.setLayout(new BoxLayout(panel, BoxLayout.LINE_AXIS));

        panel.add(title);
        panel.add(Box.createHorizontalGlue());
        panel.add(closeBtn);
        headerPanel.add(panel, BorderLayout.NORTH);
        contentPanel.add(headerPanel, BorderLayout.NORTH);
    }

    private void initControls() {
        JButton prevBtn = ComponentsHelper.createButtonWithImg(ImageHelper
                .getInstance().loadImage(Icons.LEFT_BLACK_ARROW));
        prevBtn.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                updateCalendar(false);
            }
        });

        selectedMonth.setText(dateFormat.format(calendar.getTime()));
        selectedMonth.setHorizontalAlignment(SwingConstants.CENTER);

        JButton nextBtn = ComponentsHelper.createButtonWithImg(ImageHelper
                .getInstance().loadImage(Icons.RIGHT_BLACK_ARROW));
        nextBtn.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                updateCalendar(true);
            }
        });

        JPanel panel = new JPanel(new BorderLayout());
        panel.add(prevBtn, BorderLayout.WEST);
        panel.add(selectedMonth, BorderLayout.CENTER);
        panel.add(nextBtn, BorderLayout.EAST);
        headerPanel.add(panel, BorderLayout.CENTER);
    }


    private void updateCalendar(boolean increment) {
        if (increment) {
            calendar.add(Calendar.MONTH, 1);
        } else {
            calendar.add(Calendar.MONTH, -1);
        }
        selectedMonth.setText(dateFormat.format(calendar.getTime()));
        updateCalendarValues();
    }

    private void updateCalendarValues() {
        calendar.set(Calendar.DATE, 1);
        int daysMax = calendar.getActualMaximum(Calendar.DATE);
        int monthStartIndex = calendar.get(Calendar.DAY_OF_WEEK);
        if (monthStartIndex == 1) {
            monthStartIndex = 8;
        }

        itemsPanel.removeAll();
        itemsPanel.validate();

        for (int i = 1; i <= 42; i++) {
            if (i >= monthStartIndex && i <= daysMax + monthStartIndex - 1) {
                GolfDateItem item = new GolfDateItem(calendar.getTime());
                itemsPanel.add(item);
                if (i != daysMax + monthStartIndex - 1) {
                    calendar.add(Calendar.DATE, 1);
                }
            } else {
                itemsPanel.add(new GolfDateItem(null));
            }
        }
        if (!isPrepared) {
            contentPanel.add(itemsPanel, BorderLayout.CENTER);
        }
    }

    public void show() {
        if (!isPrepared) {
            prepareDialog();
            initHeader();
            initControls();
            updateCalendarValues();
            isPrepared = true;
        }
        dialog.setLocation(source.getLocationOnScreen().x + source.getHeight()
                , source.getLocationOnScreen().y + source.getHeight());
        dialog.setVisible(true);
    }

    private class GolfDateItem extends JPanel {

        private Date date;
        private JLabel label = new JLabel();

        private GolfDateItem(Date date) {
            this.date = date;
            setPreferredSize(new Dimension(25, 10));
            if (date != null) {
                setBackground(Colors.CALENDAR_ITEM_NORMAL_STATE);
                label.setText(String.valueOf(date.getDate()));
                add(label);
                addMouseListener(new MouseAdapter() {
                    @Override
                    public void mouseClicked(MouseEvent e) {
                        dialog.setVisible(false);
                        if (calendarCallback != null) {
                            calendarCallback.updateDate(getDate());
                        }
                    }

                    @Override
                    public void mouseEntered(MouseEvent e) {
                        setBackground(Colors.CALENDAR_ITEM_HOVER_STATE);
                    }

                    @Override
                    public void mouseExited(MouseEvent e) {
                        setBackground(Colors.CALENDAR_ITEM_NORMAL_STATE);
                    }
                });
            } else {
                setBackground(Colors.CONTENT_PANEL_BACKGROUND);
            }
        }

        public Date getDate() {
            return date;
        }

    }

    public interface CalendarCallback {
        public void updateDate(Date date);
    }
}
